package org.igeek.config.InstantiationAwareBeanPostProcessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.stream.Stream;

/**
 *
 * InstantiationAwareBeanPostProcessor extends BeanPostProcessor
 * 子接口：提供的方法可以 干涉 实例化前后 以及  初始化前后
 */
@Component
public class MyAware implements InstantiationAwareBeanPostProcessor {
    /**
     *  实例化之前执行
     * @param beanClass  类类型
     * @param beanName   唯一标识
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    /**
     * 实例化之后执行
     * @param bean 实例化完成后的bean
     * @param beanName  唯一标识
     * @return  true正常返回实例 false不返回实例
     * @throws BeansException
     */
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        //作业1：判断实例是否是user类 解析@MyValue注解 来完成属性的赋值

        //1.获取类型上的所有参数
        Class<?> klass = bean.getClass();

        Field[] fields = klass.getDeclaredFields();
        //2.获取属性上是否有@MyValue的注解
        Stream.of(fields).filter(field -> field.isAnnotationPresent(MyValue.class))
                .forEach(field -> {
                    //获取注解里面的值
                    String value = field.getDeclaredAnnotation(MyValue.class).value();
                    System.out.println("value = " + value);
                    //获取变量名
                    String name = field.getName();
                    System.out.println("name = " + name);
                    //将值赋值给当前变量
                    try {
                        //3.破坏封装
                        field.setAccessible(true);
                        field.set(bean,value);
                        System.out.println("bean = " + bean);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                });
        return true;
    }

    /**
     * 初始化之前执行
     * @param bean  实例化完成后的bean
     * @param beanName  唯一标识
     * @return   处理后的bean   返回null不做任何处理
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    /**
     * 初始化之后执行
     * @param bean  实例化完成后的bean
     * @param beanName  唯一标识
     * @return  处理后的bean   返回null不做任何处理
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //作业2：对所有的bean都实现 功能增强：添加日志追踪 ==> AOP
        //1.通过反射获取bean的所有方法
        //Class<?> klass = bean.getClass();
        //
        //Method[] methods = klass.getDeclaredMethods();
        //
        //Object proxy = new JDKProxy(bean).getProxy();
/*        Stream.of(methods).forEach(method -> {
            //获取方法名
            String methodName = method.getName();

        });*/
        //2.通过
        //JDK动态代理
        if (beanName.equals("user")){

            return new JDKProxy(bean).getProxy();
        }
        return null;

    }
}
